use super::deserialize_bool;
use crate::pool;
use rbatis::{
    crud,
    rbdc::{self, db::ExecResult},
};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TbMenu {
    pub id: Option<u64>,
    pub path: String,
    pub name: String,
    pub title: String,
    pub icon: Option<String>,
    pub parent_id: Option<u64>,
    #[serde(deserialize_with = "deserialize_bool")]
    pub hidden: bool,
    pub sort: i32,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Menu {
    pub id: Option<u64>,
    pub path: String,
    pub name: String,
    pub title: String,
    pub icon: Option<String>,
    pub parent_id: Option<u64>,
    pub hidden: bool,
    pub sort: i32,
    pub routes: Option<Vec<Menu>>,
}

impl From<TbMenu> for Menu {
    fn from(value: TbMenu) -> Self {
        Self {
            id: value.id,
            path: value.path,
            name: value.name,
            title: value.title,
            icon: value.icon,
            parent_id: value.parent_id,
            hidden: value.hidden,
            sort: value.sort,
            routes: None,
        }
    }
}

impl From<Menu> for TbMenu {
    fn from(value: Menu) -> Self {
        Self {
            id: value.id,
            path: value.path,
            name: value.name,
            title: value.title,
            icon: value.icon,
            parent_id: value.parent_id,
            hidden: value.hidden,
            sort: value.sort,
        }
    }
}

crud!(TbMenu {});

impl TbMenu {
    pub async fn get_all_menu() -> Result<Vec<TbMenu>, rbdc::Error> {
        TbMenu::select_all(pool!()).await
    }

    pub async fn insert_menu(data: &mut TbMenu) -> Result<ExecResult, rbdc::Error> {
        let result = TbMenu::insert(pool!(), data).await?;
        data.id = Some(result.last_insert_id.clone().into());
        Ok(result)
    }

    pub async fn update_menu(data: &TbMenu) -> Result<ExecResult, rbdc::Error> {
        TbMenu::update_by_column(pool!(), data, "id").await
    }

    pub async fn delete_menu(id: u64) -> Result<ExecResult, rbdc::Error> {
        TbMenu::delete_by_column(pool!(), "id", id).await
    }
}
